home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / run_class.e < prev    next >
Text File  |  2000-03-25  |  57KB  |  2,038 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class RUN_CLASS
  17.    --
  18.    -- Only for class with objects at execution time.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation {SMALL_EIFFEL} make
  24.  
  25. feature
  26.  
  27.    current_type: TYPE;
  28.          -- Runnable corresponding one.
  29.  
  30.    id: INTEGER;
  31.          -- Id of the receiver to produce C code.
  32.  
  33.    at_run_time: BOOLEAN;
  34.          -- True if `current_type' is really created (only when
  35.          -- direct instances of `current_type' exists at run time).
  36.  
  37.    running: ARRAY[RUN_CLASS];
  38.          -- Void or the set of all `at_run_time' directly compatible
  39.          -- run classes. A run class is directly compatible with one
  40.          -- another only when it can be directly substitute with
  41.          -- current run class.
  42.          -- Thus, if current run class is reference, `running' are all
  43.          -- reference run classes. If current run class is expanded,
  44.          -- `running' has only one element (the current class itself).
  45.  
  46.    class_invariant: CLASS_INVARIANT;
  47.          -- Collected Runnable invariant if any.
  48.  
  49.    compile_to_c_done: BOOLEAN;
  50.          -- True if `compile_to_c' has already be called.
  51.  
  52. feature {RUN_CLASS,E_STRIP}
  53.  
  54.    feature_dictionary: DICTIONARY[RUN_FEATURE,STRING];
  55.          -- Access to the runnable version of a feature.
  56.          -- To avoid clash between infix and prefix names,
  57.          -- `to_key' of class NAME is used as entry.
  58.  
  59. feature {NONE}
  60.  
  61.    tagged_mem: INTEGER;
  62.          -- 0 when not computed, 1 when tagged or -1
  63.  
  64.    debug_info: STRING;
  65.  
  66.    make(t: like current_type) is
  67.       require
  68.          t.run_type = t
  69.       local
  70.          run_string: STRING;
  71.          rcd: DICTIONARY[RUN_CLASS,STRING];
  72.          rc: RUN_CLASS;
  73.          i: INTEGER;
  74.       do
  75.      debug
  76.         debug_info := t.run_time_mark;
  77.      end;
  78.          compile_to_c_done := true;
  79.          current_type := t;
  80.          !!actuals_clients.with_capacity(16);
  81.          run_string := t.run_time_mark;
  82.          id := id_provider.item(run_string);
  83.          check
  84.             not small_eiffel.run_class_dictionary.has(run_string);
  85.          end;
  86.          small_eiffel.run_class_dictionary.put(Current,run_string);
  87.          !!feature_dictionary.make;
  88.          small_eiffel.incr_magic_count;
  89.          if t.is_expanded then
  90.             set_at_run_time;
  91.             t.base_class.check_expanded_with(t);
  92.          else
  93.             from
  94.                rcd := small_eiffel.run_class_dictionary;
  95.                i := 1;
  96.             until
  97.                i > rcd.count
  98.             loop
  99.                rc := rcd.item(i);
  100.                if rc.at_run_time and then
  101.                   rc.current_type.is_reference and then
  102.                   rc.is_running_of(Current)
  103.                 then
  104.                   add_running(rc);
  105.                end;
  106.                i := i + 1;
  107.             end;
  108.          end;
  109.       ensure
  110.          current_type = t
  111.       end;
  112.  
  113. feature
  114.  
  115.    is_tagged: BOOLEAN is
  116.       require
  117.          small_eiffel.is_ready
  118.       do
  119.          if tagged_mem = 0 then
  120.             if current_type.is_expanded then
  121.                tagged_mem := -1;
  122.             elseif at_run_time then
  123.                if run_control.boost then
  124.                   if small_eiffel.is_tagged(Current) then
  125.                      tagged_mem := 1;
  126.                   else
  127.                      tagged_mem := -1;
  128.                   end;
  129.                else
  130.                   tagged_mem := 1;
  131.                end;
  132.             end;
  133.          end;
  134.          Result := tagged_mem = 1;
  135.       ensure
  136.          tagged_mem /= 0
  137.       end;
  138.  
  139.    is_expanded: BOOLEAN is
  140.       do
  141.          Result := current_type.is_expanded;
  142.       end;
  143.  
  144.    writable_attributes: ARRAY[RUN_FEATURE_2] is
  145.          -- Computed and ordered array of writable attributes. Storage in C 
  146.          -- struct is to be done in reverse order (from `upper' to `lower').
  147.          -- Order is done according to the level of attribute definition in 
  148.          -- the inheritance graph to allow more stupid switch to be removed.
  149.       require
  150.          small_eiffel.is_ready;
  151.          at_run_time
  152.       local
  153.          rf2: RUN_FEATURE_2;
  154.          i: INTEGER;
  155.       do
  156.          if writable_attributes_mem = Void then
  157.             from
  158.                i := 1;
  159.             until
  160.                i > feature_dictionary.count
  161.             loop
  162.                rf2 ?= feature_dictionary.item(i);
  163.                if rf2 /= Void then
  164.                   if writable_attributes_mem = Void then
  165.                      !!writable_attributes_mem.with_capacity(4,1);
  166.           end;
  167.           writable_attributes_mem.add_last(rf2);
  168.                end;
  169.                i := i + 1;
  170.             end;
  171.             if writable_attributes_mem /= Void then
  172.                sort_wam(writable_attributes_mem);
  173.             end;
  174.          end;
  175.          Result := writable_attributes_mem;
  176.       ensure
  177.          Result /= Void implies Result.lower = 1
  178.       end;
  179.  
  180.    is_running_of(other: like Current): BOOLEAN is
  181.          -- Can the Current RUN_CLASS be used in place of `other'.
  182.       require
  183.          other /= Void
  184.       local
  185.          t1, t2: TYPE;
  186.       do
  187.          if other = Current then
  188.             Result := true;
  189.          else
  190.             t1 := current_type;
  191.         t2 := other.current_type;
  192.         if t1.is_basic_eiffel_expanded and then
  193.            t2.is_basic_eiffel_expanded then
  194.         else
  195.            Result := t1.is_a(t2);
  196.            if not Result then
  197.           eh.cancel;
  198.            end;
  199.         end;
  200.          end;
  201.       ensure
  202.          nb_errors = old nb_errors
  203.       end;
  204.    
  205.    c_sizeof: INTEGER is
  206.          -- The C sizeof for an object of this RUN_CLASS on the 
  207.          -- current architecture.
  208.       require
  209.          at_run_time
  210.       local
  211.          wa: ARRAY[RUN_FEATURE_2];
  212.          a: RUN_FEATURE_2;
  213.          i: INTEGER;
  214.       do
  215.          if is_tagged then
  216.             Result := (1).object_size;
  217.          end;
  218.          wa := writable_attributes;
  219.          if wa /= Void then
  220.             from
  221.                i := wa.upper;
  222.             until
  223.                i = 0
  224.             loop
  225.                a := wa.item(i);
  226.                Result := Result + a.result_type.c_sizeof;
  227.                i := i - 1;
  228.             end;
  229.          end;
  230.          if Result = 0 then
  231.             Result := 1;
  232.          end;
  233.       end;
  234.  
  235. feature {TYPE}
  236.  
  237.    jvm_to_reference is
  238.          -- Produce code to convert the pushed expanded into the
  239.          -- corresponding TYPE_REF_TO_EXP type.
  240.       require
  241.          current_type.is_expanded
  242.       local
  243.          ref_type: TYPE;
  244.       do
  245.          ref_type := current_type.actual_reference(type_any);
  246.          ref_type.run_class.jvm_reference_from(current_type);
  247.       end;
  248.  
  249. feature {RUN_CLASS}
  250.  
  251.    jvm_reference_from(exp_type: TYPE) is
  252.       require
  253.          current_type.is_reference and exp_type.is_expanded
  254.       local
  255.          idx: INTEGER;
  256.          ca: like code_attribute;
  257.          cp: like constant_pool;
  258.       do
  259.          ca := code_attribute;
  260.          cp := constant_pool;
  261.          idx := jvm_constant_pool_index;
  262.          ca.opcode_new(idx);
  263.          ca.opcode_dup;
  264.          idx := cp.idx_methodref1(idx,fz_35,fz_29);
  265.          ca.opcode_invokespecial(idx,-1);
  266.          ca.opcode_dup_x1;
  267.          ca.opcode_swap;
  268.          tmp_string.clear;
  269.          exp_type.jvm_descriptor_in(tmp_string);
  270.          idx := cp.idx_fieldref3(fully_qualified_name,as_item,tmp_string);
  271.          ca.opcode_putfield(idx,-2);
  272.       end;
  273.  
  274. feature {TYPE_LIKE_FEATURE}
  275.  
  276.    get_result_type(fn: FEATURE_NAME): TYPE is
  277.          -- Computes only the result type of `fn' when this feature
  278.          -- is not yet runnable.
  279.          -- Possible rename is also done using the `start_position' of
  280.          -- `fn'. No return when an error occurs because `fatal_error'
  281.          -- is called.
  282.       require
  283.          not small_eiffel.is_ready;
  284.          fn /= Void
  285.       local
  286.          fn2: FEATURE_NAME;
  287.          wbc: BASE_CLASS;
  288.          rf: RUN_FEATURE;
  289.          fn2_key: STRING;
  290.          f: E_FEATURE;
  291.          bc: BASE_CLASS;
  292.       do
  293.          wbc := fn.start_position.base_class;
  294.          fn2 := base_class.new_name_of(wbc,fn);
  295.          fn2_key := fn2.to_key;
  296.          if feature_dictionary.has(fn2_key) then
  297.             rf := feature_dictionary.at(fn2_key);
  298.             Result := rf.result_type;
  299.             if Result.is_run_type then
  300.                Result := Result.run_type;
  301.             else
  302.                Result := Result.to_runnable(current_type);
  303.                Result := Result.run_type;
  304.             end;
  305.          else
  306.             bc := base_class;
  307.             f := bc.look_up_for(Current,fn2);
  308.             if f = Void then
  309.                efnf(bc,fn2);
  310.                eh.add_position(fn.start_position);
  311.                eh.add_position(fn2.start_position);
  312.                fatal_error(" Anchor not found.");
  313.             else
  314.                Result := f.result_type;
  315.                if Result = Void  then
  316.                   eh.add_position(f.start_position);
  317.                   eh.add_position(fn.start_position);
  318.                   eh.add_position(fn2.start_position);
  319.                   fatal_error(" Anchor found is a procedure.");
  320.                else
  321.                   Result := Result.to_runnable(current_type);
  322.                   Result := Result.run_type;
  323.                end;
  324.             end;
  325.          end;
  326.       ensure
  327.          Result = Result.run_type
  328.       end;
  329.  
  330. feature
  331.  
  332.    get_rf_with(fn: FEATURE_NAME): RUN_FEATURE is
  333.          -- Compute or simply fetch the corresponding RUN_FEATURE.
  334.          -- Possible rename are also done using `start_position' of
  335.          -- `fn'. No return when an error occurs because `fatal_error'
  336.          -- is called.
  337.       require
  338.          base_class = fn.start_position.base_class or else
  339.          base_class.is_subclass_of(fn.start_position.base_class)
  340.       local
  341.          fn2: FEATURE_NAME;
  342.          wbc: BASE_CLASS;
  343.       do
  344.          wbc := fn.start_position.base_class;
  345.          fn2 := base_class.new_name_of(wbc,fn);
  346.          if fn2 /= fn then
  347.             eh.add_position(fn.start_position);
  348.             Result := get_or_fatal_error(fn2);
  349.             eh.cancel;
  350.          else
  351.             Result := get_or_fatal_error(fn2);
  352.          end;
  353.       ensure
  354.          Result /= Void
  355.       end;
  356.  
  357.    dynamic(up_rf: RUN_FEATURE): RUN_FEATURE is
  358.          -- Assume the current type of `up_rf' is a kind of
  359.          -- `current_type'. The result is the concrete one
  360.          -- according to dynamic dispatch rules.
  361.       require
  362.          up_rf /= Void;
  363.          is_running_of(up_rf.run_class)
  364.       local
  365.          fn, up_fn: FEATURE_NAME;
  366.          up_type: TYPE;
  367.       do
  368.          up_type := up_rf.current_type;
  369.          if Current = up_type.run_class then
  370.             Result := up_rf;
  371.          else
  372.             up_fn := up_rf.name;
  373.             fn := base_class.new_name_of(up_type.base_class,up_fn);
  374.             Result := get_or_fatal_error(fn);
  375.          end;
  376.       ensure
  377.          Result /= Void;
  378.          Result.run_class = Current;
  379.       end;
  380.  
  381. feature
  382.  
  383.    base_class: BASE_CLASS is
  384.          -- Corresponding base class.
  385.       do
  386.          Result := current_type.base_class;
  387.       ensure
  388.          Result /= Void
  389.       end;
  390.  
  391.    base_class_name: CLASS_NAME is
  392.          -- Corresponding base class name.
  393.       do
  394.          Result := current_type.base_class_name;
  395.       ensure
  396.          Result /= Void
  397.       end;
  398.  
  399. feature
  400.  
  401.    set_at_run_time is
  402.          -- Set Current `at_run_time' and do needed update of others
  403.          -- instances of RUN_CLASS.
  404.       local
  405.          rcd: DICTIONARY[RUN_CLASS,STRING];
  406.          rc: RUN_CLASS;
  407.          i: INTEGER;
  408.       do
  409.          if not at_run_time  then
  410.             check
  411.                not small_eiffel.is_ready
  412.             end;
  413.             at_run_time := true;
  414.             compile_to_c_done := false;
  415.             add_running(Current);
  416.             small_eiffel.incr_magic_count;
  417.             if current_type.is_reference then
  418.                from
  419.                   rcd := small_eiffel.run_class_dictionary;
  420.                   i := 1;
  421.                until
  422.                   i > rcd.count
  423.                loop
  424.                   rc := rcd.item(i);
  425.                   if Current.is_running_of(rc) then
  426.                      rc.add_running(Current);
  427.                   end;
  428.                   i := i + 1;
  429.                end;
  430.             end;
  431.          end;
  432.       ensure
  433.          at_run_time;
  434.          running.has(Current)
  435.       end;
  436.  
  437. feature {TYPE}
  438.  
  439.    gc_mark_to_follow: BOOLEAN is
  440.      -- *** TO REMOVE ***
  441.       local
  442.          i: INTEGER;
  443.          r: like running;
  444.          rc: like Current;
  445.       do
  446.          r := running;
  447.          if r /= Void then
  448.             from
  449.                i := r.upper;
  450.             until
  451.                Result or else i = 0
  452.             loop
  453.                rc := r.item(i);
  454.                if rc = Current then
  455.                   Result := need_gc_mark;
  456.                else
  457.                   Result := rc.current_type.need_gc_mark_function;
  458.                end;
  459.                i := i - 1;
  460.             end;
  461.          end;
  462.       end;
  463.  
  464. feature {TYPE}
  465.  
  466.    c_print_function is
  467.       require
  468.          run_control.no_check
  469.       local
  470.          body: STRING;
  471.          ct, t: TYPE;
  472.          i: INTEGER;
  473.          wa: like writable_attributes;
  474.          rf2: RUN_FEATURE_2;
  475.       do
  476.          body := "... (to change ;-)";
  477.          ct := current_type;
  478.          tmp_string.copy("void se_prinT");
  479.          id.append_in(tmp_string);
  480.          tmp_string.append("(T");
  481.          id.append_in(tmp_string);
  482.          if ct.is_reference then
  483.             tmp_string.extend('*');
  484.          end;
  485.          tmp_string.append("*o)");
  486.          body.clear;
  487.          if ct.is_reference then
  488.             body.append("if(*o==NULL){%N%
  489.                         %fprintf(SE_ERR,%"Void%");%N%
  490.                         %return;%N}%N");
  491.          end;
  492.          body.append("fprintf(SE_ERR,%"");
  493.          body.append(ct.run_time_mark);
  494.          body.append("%");%N");
  495.          if ct.is_reference or else ct.is_native_array then
  496.             body.append("fprintf(SE_ERR,%"#%%p%",*o);%N");
  497.          end;
  498.          wa := writable_attributes;
  499.          if wa /= Void then
  500.             body.append("fprintf(SE_ERR,%"\n\t[ %");%N");
  501.             from
  502.                i := wa.upper;
  503.             until
  504.                i = 0
  505.             loop
  506.                rf2 := wa.item(i);
  507.                t := rf2.result_type;
  508.                body.append("fprintf(SE_ERR,%"");
  509.                body.append(rf2.name.to_string);
  510.                body.append(" = %");%Nse_prinT");
  511.                if t.is_expanded then
  512.                   t.id.append_in(body);
  513.                elseif t.is_string then
  514.                   body.extend('7');
  515.                else
  516.                   body.extend('0');
  517.                end;
  518.                body.append("((void*)(&((*o)");
  519.                if ct.is_reference then
  520.                   body.append("->");
  521.                else
  522.                   body.extend('.');
  523.                end;
  524.                body.extend('_');
  525.                body.append(rf2.name.to_string);
  526.                body.append(")));%N");
  527.                i := i - 1;
  528.                if i > 0 then
  529.                   body.append("fprintf(SE_ERR,%"\n\t  %");%N");
  530.                end;
  531.             end;
  532.             body.append("fprintf(SE_ERR,%"\n\t]%");%N");
  533.          end;
  534.          cpp.put_c_function(tmp_string,body);
  535.       end;
  536.  
  537.    c_object_model_in(str: STRING) is
  538.       local
  539.          wa: like writable_attributes;
  540.          i: INTEGER;
  541.          rf2: RUN_FEATURE_2;
  542.          t: TYPE;
  543.       do
  544.          wa := writable_attributes;
  545.          if wa = Void then
  546.             if is_tagged then
  547.                str.extend('{');
  548.                id.append_in(str);
  549.                str.extend('}');
  550.             else
  551.                current_type.c_initialize_in(str);
  552.             end;
  553.          else
  554.             str.extend('{');
  555.             if is_tagged then
  556.                id.append_in(str);
  557.                str.extend(',');
  558.             end;
  559.             from
  560.                i := wa.upper;
  561.             until
  562.                i = 0
  563.             loop
  564.                rf2 := wa.item(i);
  565.                t := rf2.result_type;
  566.                t.c_initialize_in(str);
  567.                i := i - 1;
  568.                if i > 0 then
  569.                   str.extend(',');
  570.                end;
  571.             end;
  572.             str.extend('}');
  573.          end;
  574.       end;
  575.  
  576. feature {SMALL_EIFFEL}
  577.  
  578.    falling_down is
  579.          -- Falling down of Current `feature_dictionary' in `running'.
  580.       local
  581.          rf: RUN_FEATURE;
  582.          i: INTEGER;
  583.       do
  584.          from
  585.             i := 1;
  586.          until
  587.             i > feature_dictionary.count
  588.          loop
  589.             rf := feature_dictionary.item(i);
  590.             rf.fall_down;
  591.             i := i + 1;
  592.          end;
  593.          gc_handler.falling_down(Current);
  594.          runnable_class_invariant;
  595.      if run_control.deep_twin_used then
  596.         if current_type.is_native_array then
  597.            rf := get_feature_with(as_deep_twin_from);
  598.         else
  599.            rf := get_feature_with(as_deep_twin);
  600.         end;
  601.      end;
  602.      if run_control.is_deep_equal_used then
  603.         if current_type.is_native_array then
  604.            rf := get_feature_with(as_deep_memcmp);
  605.         else
  606.            rf := get_feature_with(as_deep_equal);
  607.            rf := get_feature_with(as_is_deep_equal);
  608.         end;
  609.      end;
  610.       end;
  611.  
  612.    afd_check is
  613.          -- After Falling Down Check.
  614.       local
  615.          rf: RUN_FEATURE;
  616.          i: INTEGER;
  617.          rc: like Current;
  618.          rt: TYPE;
  619.       do
  620.          from
  621.             i := 1;
  622.          until
  623.             i > feature_dictionary.count
  624.          loop
  625.             rf := feature_dictionary.item(i);
  626.             rf.afd_check;
  627.             rt := rf.result_type;
  628.             if rt /= Void then
  629.                if rt.is_none then
  630.                else
  631.                   rc := rt.run_class;
  632.                end;
  633.             end;
  634.             i := i + 1;
  635.          end;
  636.          if class_invariant /= Void then
  637.             class_invariant.afd_check;
  638.          end;
  639.       end;
  640.  
  641. feature {SHORT}
  642.  
  643.    runnable_class_invariant is
  644.       do
  645.          if not runnable_class_invariant_done then
  646.             runnable_class_invariant_done := true;
  647.             if run_control.invariant_check then
  648.                if at_run_time or else small_eiffel.short_flag then
  649.                   assertion_collector.invariant_start;
  650.                   base_class.collect_invariant(Current);
  651.                   class_invariant := assertion_collector.invariant_end(current_type);
  652.                end;
  653.             end;
  654.          end;
  655.       end;
  656.  
  657. feature
  658.  
  659.    c_header_pass1 is
  660.       require
  661.          cpp.on_h
  662.       do
  663.          if at_run_time then
  664.             if c_header_pass_level_done < 1 then
  665.                current_type.c_header_pass1;
  666.                c_header_pass_level_done := 1;
  667.             end;
  668.          end;
  669.       ensure
  670.          cpp.on_h
  671.       end;
  672.  
  673.    c_header_pass2 is
  674.       require
  675.          cpp.on_h
  676.       do
  677.          if at_run_time then
  678.             if c_header_pass_level_done < 2 then
  679.                current_type.c_header_pass2;
  680.                c_header_pass_level_done := 2;
  681.             end;
  682.          end;
  683.       ensure
  684.          cpp.on_h
  685.       end;
  686.  
  687.    c_header_pass3 is
  688.       require
  689.          cpp.on_h
  690.       local
  691.          i: INTEGER;
  692.          attribute_type: TYPE;
  693.       do
  694.          if at_run_time then
  695.             if c_header_pass_level_done < 3 then
  696.                if current_type.is_user_expanded and then
  697.                   writable_attributes /= Void
  698.                 then
  699.                   from
  700.                      i := writable_attributes.upper;
  701.                   until
  702.                      i = 0
  703.                   loop
  704.                      attribute_type := writable_attributes.item(i).result_type;
  705.                      if attribute_type.is_expanded then
  706.                         attribute_type.run_class.c_header_pass3;
  707.                      end;
  708.                      i := i - 1;
  709.                   end;
  710.                end;
  711.                current_type.c_header_pass3;
  712.                c_header_pass_level_done := 3;
  713.             end;
  714.          end;
  715.       ensure
  716.          cpp.on_h
  717.       end;
  718.  
  719.    c_header_pass4 is
  720.       require
  721.          cpp.on_h
  722.       do
  723.          if at_run_time then
  724.             if c_header_pass_level_done < 4 then
  725.                current_type.c_header_pass4;
  726.                c_header_pass_level_done := 4;
  727.             end;
  728.          end;
  729.       ensure
  730.          cpp.on_h
  731.       end;
  732.  
  733. feature {GC_HANDLER}
  734.  
  735.    get_memory_dispose: RUN_FEATURE_3 is
  736.       local
  737.          memory, bc: BASE_CLASS;
  738.       do
  739.          memory := small_eiffel.memory_class_used;
  740.          if memory /= Void then
  741.             bc := base_class;
  742.             if memory /= bc and then bc.is_subclass_of(memory) then
  743.                if bc.has_simple_feature_name(as_dispose) then
  744.                   Result ?= get_feature_with(as_dispose);
  745.                   if Result /= Void then
  746.                      Result := Result.memory_dispose;
  747.                  end;
  748.                end;
  749.             end;
  750.          end;
  751.       end;
  752.  
  753.    gc_define1 is
  754.       require
  755.          not gc_handler.is_off
  756.       do
  757.          if at_run_time then
  758.             current_type.gc_define1;
  759.          end;
  760.       end;
  761.  
  762.    gc_define2 is
  763.       require
  764.          not gc_handler.is_off
  765.       do
  766.          if at_run_time then
  767.             current_type.gc_define2;
  768.          end;
  769.       end;
  770.  
  771.    gc_info_in(str: STRING) is
  772.          -- Produce C code to print GC information.
  773.       require
  774.          not gc_handler.is_off;
  775.          gc_handler.info_flag
  776.       do
  777.          if at_run_time then
  778.             current_type.gc_info_in(str);
  779.          end;
  780.       end;
  781.  
  782.    just_before_gc_mark_in(body: STRING) is
  783.       require
  784.          not gc_handler.is_off
  785.       do
  786.          if at_run_time then
  787.             current_type.just_before_gc_mark_in(body);
  788.          end;
  789.       end;
  790.  
  791.    gc_initialize is
  792.          -- Produce code to initialize GC in the main C function.
  793.       require
  794.          not gc_handler.is_off
  795.       do
  796.          if at_run_time then
  797.             current_type.gc_initialize;
  798.          end;
  799.       end;
  800.  
  801. feature {TYPE}
  802.  
  803.    gc_mark_fixed_size(is_unmarked: BOOLEAN; body: STRING) is
  804.          -- The main purpose is to compute for example the best body for 
  805.          -- the corresponding gc_markXXX function (as well as 
  806.          -- gc_align_markXXX). In fact, this feature can be called to 
  807.          -- produce C code when C variable `o' is not NULL and when `o' is of 
  808.          -- some concrete type (Tid*) where `id' is the one of the current 
  809.          -- RUN_CLASS. -- Finally, when `is_unmarked' is true, object `o' is 
  810.          -- unmarked.
  811.       require
  812.          not gc_handler.is_off;
  813.          not current_type.is_native_array;
  814.          at_run_time
  815.       local
  816.          rf2: RUN_FEATURE_2;
  817.          t: TYPE;
  818.          rc: RUN_CLASS;
  819.          i: INTEGER;
  820.       do
  821.          wa_buf.clear;
  822.          wa_cyclic_buf.clear;
  823.          if writable_attributes /= Void then
  824.             from
  825.                i := writable_attributes.upper;
  826.             until
  827.                i = 0
  828.             loop
  829.                rf2 := writable_attributes.item(i);
  830.                t := rf2.result_type;
  831.                if t.need_gc_mark_function then
  832.                   rc :=  t.run_class;
  833.                   wa_cycle.clear;
  834.                   wa_cycle.add_last(rf2);
  835.                   if rc.is_wa_cycle(Current) then
  836.                      wa_cyclic_buf.add_last(rf2);
  837.                   else
  838.                      wa_buf.add_last(rf2);
  839.                   end;
  840.                end;
  841.                i := i - 1;
  842.             end;
  843.          end;
  844.          if wa_buf.is_empty and then wa_cyclic_buf.is_empty then
  845.             gc_set_fsoh_marked_in(body);
  846.          else
  847.             if wa_cyclic_buf.upper >= 0 then
  848.                body.append("begin:%N");
  849.             end;
  850.             if not is_unmarked then
  851.                body.append(
  852.                   "if(((gc");
  853.                id.append_in(body);
  854.                body.append(
  855.                   "*)o)->header.flag==FSOH_UNMARKED){%N");
  856.             end;
  857.             gc_set_fsoh_marked_in(body);
  858.             from -- Ordinary attributes :
  859.                i := wa_buf.upper;
  860.             until
  861.                i < 0
  862.             loop
  863.                rf2 := wa_buf.item(i);
  864.                mark_attribute(body,rf2);
  865.                i := i - 1;
  866.             end;
  867.             from -- Cyclic attributes :
  868.                i := wa_cyclic_buf.upper;
  869.             until
  870.                i < 0
  871.             loop
  872.                rf2 := wa_cyclic_buf.item(i);
  873.                t := rf2.result_type;
  874.                rc :=  t.run_class;
  875.                wa_cycle.clear;
  876.                wa_cycle.add_last(rf2);
  877.                if rc.is_wa_cycle(Current) then
  878.                end;
  879.                if i = 0 and then
  880.                   wa_cycle.count = 1 and then
  881.                   rc.running /= Void and then
  882.                   rc.running.count = 1 and then
  883.                   rc.running.first = Current
  884.                 then
  885.                   body.append("o=(void*)o->_");
  886.                   body.append(rf2.name.to_string);
  887.                   body.append(";%Nif((o!=NULL)");
  888.                   if is_unmarked then
  889.                      body.append("&&(((gc");
  890.                      id.append_in(body);
  891.                      body.append(
  892.                         "*)o)->header.flag==FSOH_UNMARKED))");
  893.                   else
  894.                      body.extend(')');
  895.                   end;
  896.                   body.append("goto begin;%N");
  897.                else
  898.                   mark_attribute(body,rf2);
  899.                end;
  900.                i := i - 1;
  901.             end;
  902.             if not is_unmarked then
  903.                body.extend('}');
  904.             end;
  905.          end;
  906.       end;
  907.  
  908. feature {TYPE}
  909.  
  910.    gc_align_mark_fixed_size(body: STRING) is
  911.          -- Compute the best body for gc_align_markXXX of
  912.          -- a fixed_size object.
  913.       require
  914.          not gc_handler.is_off;
  915.          not current_type.is_native_array;
  916.          at_run_time
  917.       do
  918.          body.append(fz_gc);
  919.          id.append_in(body);
  920.          body.append("*b=((gc");
  921.          id.append_in(body);
  922.      body.append(
  923.             "*)(&(c->first_object)));%N%
  924.             %if((c->header.state_type==FSO_STORE_CHUNK)%
  925.             %&&(((char*)p)>=((char*)store");
  926.          id.append_in(body);
  927.          body.append(
  928.             ")))return;%N%
  929.             %if(((char*)p)>((char*)(b+(c->count_minus_one))))return;%N%
  930.             %if(((char*)p)<((char*)b))return;%N%
  931.             %if(((((char*)p)-((char*)b))%%sizeof(*p))==0){%N%
  932.             %if(p->header.flag==FSOH_UNMARKED){%N%
  933.             %T");
  934.          id.append_in(body);
  935.          body.append("*o=(&(p->object));%N");
  936.          gc_mark_fixed_size(true,body);
  937.          body.append("}%N}%N");
  938.       end;
  939.  
  940. feature {RUN_CLASS}
  941.  
  942.    fill_up_with(rc: RUN_CLASS; fd: like feature_dictionary) is
  943.          -- Fill up `feature_dictionary' with all features coming from
  944.          -- `rc' X `fd'.
  945.       require
  946.          rc /= Current;
  947.          is_running_of(rc);
  948.          fd /= Void;
  949.       local
  950.          bc1, bc2: BASE_CLASS;
  951.          fn1, fn2: FEATURE_NAME;
  952.          rf: RUN_FEATURE;
  953.          i: INTEGER;
  954.       do
  955.          from
  956.             i := 1;
  957.             bc1 := rc.base_class;
  958.             bc2 := base_class;
  959.          until
  960.             i > fd.count
  961.          loop
  962.             rf := fd.item(i);
  963.             if rf.fall_in(Current) then
  964.                fn1 := rf.name;
  965.                fn2 := bc2.name_of(bc1,fn1);
  966.                rf := get_feature(fn2);
  967.             end;
  968.             i := i + 1;
  969.          end;
  970.       end;
  971.  
  972.    add_running(rc: RUN_CLASS) is
  973.       require
  974.          rc /= Void;
  975.       do
  976.          if running = Void then
  977.         !!running.with_capacity(8,1);
  978.         running.add_last(rc);
  979.          else
  980.             if not running.fast_has(rc) then
  981.                running.add_last(rc);
  982.             end;
  983.          end;
  984.       end;
  985.  
  986. feature {E_FEATURE}
  987.  
  988.    at(fn: FEATURE_NAME): RUN_FEATURE is
  989.          -- Simple look in the dictionary to see if the feature
  990.          -- is already computed.
  991.       require
  992.          fn /= Void;
  993.       local
  994.          to_key: STRING;
  995.       do
  996.          to_key := fn.to_key;
  997.          if feature_dictionary.has(to_key) then
  998.             Result := feature_dictionary.at(to_key);
  999.          end;
  1000.       end;
  1001.  
  1002. feature
  1003.  
  1004.    get_feature_with(n: STRING): RUN_FEATURE is
  1005.          -- Assume that `n' is really the final name in current RUN_CLASS.
  1006.       require
  1007.          n /= Void;
  1008.       local
  1009.          sfn: SIMPLE_FEATURE_NAME;
  1010.       do
  1011.          if feature_dictionary.has(n) then
  1012.             Result := feature_dictionary.at(n);
  1013.          else
  1014.             !!sfn.unknown_position(n);
  1015.             Result := get_feature(sfn);
  1016.          end;
  1017.       end;
  1018.  
  1019. feature
  1020.  
  1021.    get_copy: RUN_FEATURE is
  1022.       do
  1023.          Result := get_rf_with(class_general.get_copy.first_name);
  1024.       end;
  1025.  
  1026.    get_feature(fn: FEATURE_NAME): RUN_FEATURE is
  1027.          -- Assume that `fn' is really the final name in current
  1028.          -- RUN_CLASS. Don't look for rename.
  1029.       require
  1030.          fn /= Void
  1031.       local
  1032.          f: E_FEATURE;
  1033.          fn_key: STRING;
  1034.          bc: BASE_CLASS;
  1035.       do
  1036.          fn_key := fn.to_key;
  1037.          if feature_dictionary.has(fn_key) then
  1038.             Result := feature_dictionary.at(fn_key);
  1039.          else
  1040.             check
  1041.                not small_eiffel.is_ready;
  1042.             end;
  1043.             bc := base_class;
  1044.             f := bc.look_up_for(Current,fn);
  1045.             if f = Void then
  1046.                efnf(bc,fn);
  1047.             else
  1048.                Result := f.to_run_feature(current_type,fn);
  1049.                if Result /= Void  then
  1050.                   store_feature(Result);
  1051.                else
  1052.                   efnf(bc,fn);
  1053.                end;
  1054.             end;
  1055.          end;
  1056.       end;
  1057.  
  1058. feature {JVM}
  1059.  
  1060.    jvm_define_class_invariant is
  1061.          -- If needed, call the invariant for the pushed value.
  1062.       local
  1063.          ia: like class_invariant;
  1064.       do
  1065.          if run_control.invariant_check then
  1066.             ia := class_invariant;
  1067.             if ia /= Void then
  1068.                jvm.define_class_invariant_method(ia);
  1069.             end;
  1070.          end;
  1071.       end;
  1072.  
  1073. feature {JVM,TYPE}
  1074.  
  1075.    jvm_check_class_invariant is
  1076.          -- If needed, call the invariant for the stack-top object.
  1077.          -- If invariant is correct, the same stack-top object is left
  1078.          -- on the stack.
  1079.       local
  1080.          ia: like class_invariant;
  1081.          idx: INTEGER;
  1082.          ca: like code_attribute;
  1083.          cp: like constant_pool;
  1084.       do
  1085.          if run_control.invariant_check then
  1086.             ia := class_invariant;
  1087.             if ia /= Void then
  1088.                ca := code_attribute;
  1089.                cp := constant_pool;
  1090.                ca.opcode_dup;
  1091.                opcode_checkcast;
  1092.                idx := cp.idx_methodref3(fully_qualified_name,fz_invariant,fz_29);
  1093.                ca.opcode_invokevirtual(idx,-1);
  1094.             end;
  1095.          end;
  1096.       end;
  1097.  
  1098. feature {SMALL_EIFFEL}
  1099.  
  1100.    compile_to_jvm is
  1101.       require
  1102.          at_run_time
  1103.       local
  1104.          i: INTEGER;
  1105.          rf: RUN_FEATURE;
  1106.          type_ref_to_exp: TYPE_REF_TO_EXP;
  1107.       do
  1108.          echo.put_character('%T');
  1109.          echo.put_string(current_type.run_time_mark);
  1110.          echo.put_character('%N');
  1111.          jvm.start_new_class(Current);
  1112.          from
  1113.             i := 1;
  1114.          until
  1115.             i > feature_dictionary.count
  1116.          loop
  1117.             rf := feature_dictionary.item(i);
  1118.             jvm.set_current_frame(rf);
  1119.             rf.jvm_field_or_method;
  1120.             i := i + 1;
  1121.          end;
  1122.          type_ref_to_exp ?= current_type;
  1123.          if type_ref_to_exp = Void then
  1124.             jvm.prepare_fields;
  1125.          else
  1126.             type_ref_to_exp.jvm_prepare_item_field;
  1127.          end;
  1128.          jvm.prepare_methods;
  1129.          jvm.finish_class;
  1130.       end;
  1131.  
  1132. feature {MANIFEST_ARRAY}
  1133.  
  1134.    fully_qualified_name: STRING is
  1135.       do
  1136.          if fully_qualified_name_memory = Void then
  1137.             fully_qualified_name_memory2.copy(run_control.output_name);
  1138.             fully_qualified_name_memory2.extend('/');
  1139.             fully_qualified_name_memory2.append(unqualified_name);
  1140.             !!fully_qualified_name_memory.copy(fully_qualified_name_memory2);
  1141.          end;
  1142.          Result := fully_qualified_name_memory;
  1143.       end;
  1144.  
  1145. feature {TYPE}
  1146.  
  1147.    jvm_type_descriptor_in(str: STRING) is
  1148.          -- Append in `str' the appropriate JVM type descriptor.
  1149.       require
  1150.          at_run_time;
  1151.          running.fast_has(Current)
  1152.       do
  1153.          check
  1154.             current_type.is_user_expanded
  1155.          end;
  1156.          str.extend('L');
  1157.          str.append(fully_qualified_name);
  1158.          str.extend(';');
  1159.       end;
  1160.  
  1161. feature {RUN_FEATURE}
  1162.  
  1163.    jvm_invoke(idx, stack_level: INTEGER) is
  1164.       local
  1165.          ct: like current_type;
  1166.       do
  1167.          ct := current_type;
  1168.          inspect
  1169.             ct.jvm_method_flags
  1170.          when 17 then
  1171.             code_attribute.opcode_invokevirtual(idx,stack_level);
  1172.          when 9 then
  1173.             code_attribute.opcode_invokestatic(idx,stack_level);
  1174.          end;
  1175.       end;
  1176.  
  1177. feature
  1178.  
  1179.    jvm_basic_new is
  1180.          -- Poduce bytecode to push a new created object with the
  1181.          -- basic default value (the corresponding creation procedure
  1182.          -- if any is not called).
  1183.       local
  1184.          i, idx: INTEGER;
  1185.          wa: ARRAY[RUN_FEATURE_2];
  1186.          rf2: RUN_FEATURE_2;
  1187.          t2: TYPE;
  1188.          ca: like code_attribute;
  1189.          cp: like constant_pool;
  1190.       do
  1191.          ca := code_attribute;
  1192.          cp := constant_pool;
  1193.          idx := jvm_constant_pool_index;
  1194.          ca.opcode_new(idx);
  1195.          ca.opcode_dup;
  1196.            idx := cp.idx_methodref1(idx,fz_35,fz_29);
  1197.          ca.opcode_invokespecial(idx,-1);
  1198.          wa := writable_attributes;
  1199.          if wa /= Void then
  1200.             from
  1201.                i := wa.upper;
  1202.             until
  1203.                i = 0
  1204.             loop
  1205.                rf2 := wa.item(i);
  1206.                t2 := rf2.result_type.run_type;
  1207.                if t2.is_user_expanded then
  1208.                   ca.opcode_dup;
  1209.                   t2.run_class.jvm_expanded_push_default;
  1210.                   idx := cp.idx_fieldref(rf2);
  1211.                   ca.opcode_putfield(idx,-2);
  1212.                elseif t2.is_bit then
  1213.                   ca.opcode_dup;
  1214.                   idx := t2.jvm_push_default;
  1215.                   idx := cp.idx_fieldref(rf2);
  1216.                   ca.opcode_putfield(idx,-2);
  1217.                end;
  1218.                i := i - 1;
  1219.             end;
  1220.          end;
  1221.       end;
  1222.  
  1223. feature {TYPE,RUN_CLASS,NATIVE_SMALL_EIFFEL}
  1224.  
  1225.    jvm_expanded_push_default is
  1226.          -- Push the corresponding new user's expanded (either dummy
  1227.          -- or not, initializer is automatically applied).
  1228.       require
  1229.          current_type.is_user_expanded
  1230.       local
  1231.          rf: RUN_FEATURE;
  1232.       do
  1233.          jvm_basic_new;
  1234.          rf := base_class.expanded_initializer(current_type);
  1235.          if rf /= Void then
  1236.             jvm.push_expanded_initialize(rf);
  1237.             rf.mapping_jvm;
  1238.             jvm.pop;
  1239.          end;
  1240.       end;
  1241.  
  1242. feature {NATIVE_SMALL_EIFFEL}
  1243.  
  1244.    deep_twin_in(body: STRING) is
  1245.       local
  1246.      i: INTEGER;
  1247.          wa: ARRAY[RUN_FEATURE_2];
  1248.      rf2: RUN_FEATURE_2;
  1249.      t: TYPE;
  1250.      name: STRING;
  1251.       do
  1252.      if current_type.is_reference then
  1253.         body.append("R=se_deep_twin_search((void*)C);%N%
  1254.             %if(R == NULL){%N");
  1255.         current_type.c_type_for_target_in(body);
  1256.         body.extend(' ');
  1257.         gc_handler.basic_allocation("new",body,Current);
  1258.         body.append("R=((T0*)new);%N%
  1259.             %*new=*C;%N%
  1260.             %se_deep_twin_register(((T0*)C),((T0*)new));%N");
  1261.          else
  1262.         body.append("se_deep_twin_start();%N%
  1263.             %R=*C;%N{");
  1264.         current_type.c_type_for_target_in(body);
  1265.         body.append(" new=&(R);%N");
  1266.      end;
  1267.          wa := writable_attributes;
  1268.          if wa /= Void then
  1269.             from
  1270.                i := wa.upper;
  1271.             until
  1272.                i = 0
  1273.             loop
  1274.                rf2 := wa.item(i);
  1275.            name := rf2.name.to_string;
  1276.                t := rf2.result_type.run_type;
  1277.            if t.is_reference then
  1278.           body.append("if(new->_");
  1279.           body.append(name);
  1280.           body.append("!=NULL){%N%
  1281.                   %new->_");
  1282.           body.append(name);
  1283.           body.append("=X10deep_twin(");
  1284.           if run_control.no_check then
  1285.              body.append("&ds,ds.p,");
  1286.           end;
  1287.           body.append("new->_");
  1288.           body.append(name);
  1289.           body.append(");%N}%N");
  1290.            elseif t.is_native_array then
  1291.           if get_feature_with(as_capacity) = Void then
  1292.              eh.add_type(t,fz_dtideena);
  1293.              eh.print_as_error;
  1294.              eh.add_position(rf2.start_position);
  1295.              eh.append(em1);
  1296.              eh.print_as_fatal_error;
  1297.           end;
  1298.           body.append("new->_");
  1299.           body.append(name);
  1300.           body.append("=r");
  1301.           t.id.append_in(body);
  1302.           body.append("deep_twin_from(");
  1303.           if run_control.no_check then
  1304.              body.append("&ds,");
  1305.           end;
  1306.           body.append("new->_");
  1307.           body.append(name);
  1308.           body.append(",new->_capacity);%N");
  1309.            elseif t.is_user_expanded then
  1310.           body.append("new->_");
  1311.           body.append(name);
  1312.           body.append("=r");
  1313.           t.id.append_in(body);
  1314.           body.append("deep_twin(");
  1315.           if run_control.no_check then
  1316.              body.append("&ds,");
  1317.           end;
  1318.           body.append("&(new->_");
  1319.           body.append(name);
  1320.           body.append("));%N");
  1321.                else
  1322.                end;
  1323.                i := i - 1;
  1324.             end;
  1325.          end;
  1326.      if current_type.is_user_expanded then
  1327.         body.append("se_deep_twin_trats(NULL);%N");
  1328.      end;
  1329.      body.extend('}');
  1330.      body.extend('%N');
  1331.       end;
  1332.  
  1333.    is_deep_equal_in(body: STRING) is
  1334.       local
  1335.      i: INTEGER;
  1336.          wa: ARRAY[RUN_FEATURE_2];
  1337.      rf2: RUN_FEATURE_2;
  1338.      ct, t: TYPE;
  1339.      name: STRING;
  1340.       do
  1341.      ct := current_type;
  1342.      body.append("se_deep_equal_start();%N");
  1343.      if ct.is_reference then
  1344.         body.append("R=se_deep_equal_search(C,a1);%N");
  1345.      end;
  1346.      body.append("if(!R){%N");
  1347.      ct.c_type_for_target_in(body);
  1348.      body.append("deep=");
  1349.      if ct.is_reference then
  1350.         body.append("((void*)a1);%N");
  1351.      else
  1352.         body.append("((void*)(&a1));%N");
  1353.      end;
  1354.      body.append("R=1;%N");
  1355.          wa := writable_attributes;
  1356.          if wa /= Void then
  1357.             from
  1358.                i := wa.upper;
  1359.             until
  1360.                i = 0
  1361.             loop
  1362.                rf2 := wa.item(i);
  1363.            name := rf2.name.to_string;
  1364.                t := rf2.result_type.run_type;
  1365.            if t.is_basic_eiffel_expanded then
  1366.           body.append("if(R)R=((C->_");
  1367.           body.append(name);
  1368.           body.append(")==(deep->_");
  1369.           body.append(name);
  1370.           body.append("));%N");
  1371.                end;
  1372.                i := i - 1;
  1373.             end;
  1374.             from
  1375.                i := wa.upper;
  1376.             until
  1377.                i = 0
  1378.             loop
  1379.                rf2 := wa.item(i);
  1380.            name := rf2.name.to_string;
  1381.                t := rf2.result_type.run_type;
  1382.            if t.is_reference then
  1383.           body.append("if(R)R=r");
  1384.           ct.id.append_in(body);
  1385.           body.append("deep_equal(");
  1386.           if run_control.no_check then
  1387.              body.append("&ds,");
  1388.              if ct.is_reference then
  1389.             body.append("C,");
  1390.              end;
  1391.           end;
  1392.           body.append("C->_");
  1393.           body.append(name);
  1394.           body.append(",deep->_");
  1395.           body.append(name);
  1396.           body.append(");%N");
  1397.            elseif t.is_native_array then
  1398.           if get_feature_with(as_capacity) = Void then
  1399.              eh.add_type(t,fz_dtideena);
  1400.              eh.print_as_error;
  1401.              eh.add_position(rf2.start_position);
  1402.              eh.append(em1);
  1403.              eh.print_as_fatal_error;
  1404.               end;
  1405.           body.append("if(R)R=r");
  1406.           t.id.append_in(body);
  1407.           body.append("deep_memcmp(");
  1408.           if run_control.no_check then
  1409.              body.append("&ds,");
  1410.           end;
  1411.           body.append("C->_");
  1412.           body.append(name);
  1413.           body.append(",deep->_");
  1414.           body.append(name);
  1415.           body.append(",C->_capacity);%N");
  1416.            elseif t.is_user_expanded then
  1417.           body.append("if(R)R=r");
  1418.           t.id.append_in(body);
  1419.           body.append("is_deep_equal(");
  1420.           if run_control.no_check then
  1421.              body.append("&ds,");
  1422.           end;
  1423.           body.append("&(C->_");
  1424.           body.append(name);
  1425.           body.append("),deep->_");
  1426.           body.append(name);
  1427.           body.append(");%N");
  1428.                else
  1429.                end;
  1430.                i := i - 1;
  1431.             end;
  1432.          end;
  1433.      body.append("}%Nse_deep_equal_trats();%N");
  1434.       end;
  1435.  
  1436. feature {JVM}
  1437.  
  1438.    unqualified_name: STRING is
  1439.          -- Also used for the corresponding file name.
  1440.       local
  1441.          ct: TYPE;
  1442.       do
  1443.          ct := current_type;
  1444.          unqualified_name_memory.copy(ct.run_time_mark);
  1445.          unqualified_name_memory.to_lower;
  1446.          unqualified_name_memory.replace_all('[','O');
  1447.          unqualified_name_memory.replace_all(']','F');
  1448.          unqualified_name_memory.replace_all(' ','_');
  1449.          unqualified_name_memory.replace_all(',','_');
  1450.          Result := unqualified_name_memory;
  1451.       end;
  1452.  
  1453. feature
  1454.  
  1455.    jvm_constant_pool_index: INTEGER is
  1456.          -- The fully qualified index in the constant pool.
  1457.       do
  1458.          Result := constant_pool.idx_class2(fully_qualified_name);
  1459.       end;
  1460.  
  1461. feature {SMALL_EIFFEL}
  1462.  
  1463.    demangling is
  1464.       require
  1465.          cpp.on_h
  1466.       local
  1467.          str: STRING;
  1468.          r: like running;
  1469.          i: INTEGER;
  1470.       do
  1471.          str := "......................................................";
  1472.          str.clear;
  1473.          if at_run_time then
  1474.             str.extend('A');
  1475.             if current_type.is_reference and then not is_tagged then
  1476.                str.extend('*');
  1477.             else
  1478.                str.extend(' ');
  1479.             end;
  1480.          else
  1481.             str.extend('D');
  1482.             str.extend(' ');
  1483.          end;
  1484.          r := running;
  1485.          if r /= Void then
  1486.             r.count.append_in(str);
  1487.          end;
  1488.          from
  1489.          until
  1490.             str.count > 4
  1491.          loop
  1492.             str.extend(' ');
  1493.          end;
  1494.          str.extend('T');
  1495.          id.append_in(str);
  1496.          from
  1497.          until
  1498.             str.count > 10
  1499.          loop
  1500.             str.extend(' ');
  1501.          end;
  1502.          current_type.demangling_in(str);
  1503.          if r /= Void then
  1504.             from
  1505.                str.extend(' ');
  1506.                i := r.upper;
  1507.             until
  1508.                i = 0
  1509.             loop
  1510.                r.item(i).id.append_in(str);
  1511.                i := i - 1;
  1512.                if i > 0 then
  1513.                   str.extend(',');
  1514.                end;
  1515.             end;
  1516.          end;
  1517.          str.extend('%N');
  1518.          cpp.put_string(str);
  1519.       ensure
  1520.          cpp.on_h
  1521.       end;
  1522.  
  1523.    id_extra_information(sfw: STD_FILE_WRITE) is
  1524.       local
  1525.          r: like running;
  1526.          i: INTEGER;
  1527.          ct: TYPE;
  1528.       do
  1529.          ct := current_type;
  1530.          sfw.put_string("c-type: T");
  1531.          sfw.put_integer(id);
  1532.          sfw.put_character(' ');
  1533.          ct.id_extra_information(sfw);
  1534.          if ct.is_reference then
  1535.             sfw.put_string("ref-status: ");
  1536.             if at_run_time then
  1537.                sfw.put_string("live id-field: ");
  1538.                if ct.is_reference and then not is_tagged then
  1539.                   sfw.put_string("no ");
  1540.                else
  1541.                   sfw.put_string("yes ");
  1542.                end;
  1543.             else
  1544.                sfw.put_string("dead ");
  1545.             end;
  1546.             sfw.put_string("running-count: ");
  1547.             r := running;
  1548.             if r /= Void then
  1549.                sfw.put_integer(r.count);
  1550.             else
  1551.                sfw.put_character('0');
  1552.             end;
  1553.             sfw.put_character(' ');
  1554.             if r /= Void then
  1555.                sfw.put_string("running: ");
  1556.                from
  1557.                   i := r.upper;
  1558.                until
  1559.                   i = 0
  1560.                loop
  1561.                   sfw.put_integer(r.item(i).id);
  1562.                   sfw.put_character(' ');
  1563.                   i := i - 1;
  1564.                end;
  1565.             end;
  1566.          end;
  1567.       end;
  1568.    
  1569. feature {SMALL_EIFFEL,RUN_CLASS}
  1570.  
  1571.    compile_to_c(deep: INTEGER) is
  1572.          -- Produce C code for features of Current. The `deep'
  1573.          -- indicator is used to sort the C output in the best order
  1574.          -- (more C  inlinings are possible when basic functions are
  1575.          -- produced first). As there is not always a total order
  1576.          -- between clients, the `deep' avoid infinite track.
  1577.          -- When `deep' is greater than 0, C code writting
  1578.          -- is produced whatever the real client relation is.
  1579.       require
  1580.          cpp.on_c;
  1581.          deep >= 0
  1582.       local
  1583.          i: INTEGER;
  1584.          rc1, rc2: like Current;
  1585.          cc1, cc2: INTEGER;
  1586.       do
  1587.          if compile_to_c_done then
  1588.          elseif not at_run_time then
  1589.             compile_to_c_done := true;
  1590.          elseif deep = 0 then
  1591.             really_compile_to_c;
  1592.          else
  1593.             i := actuals_clients.upper;
  1594.             if i >= 0 then
  1595.                from
  1596.                   rc1 := Current;
  1597.                   cc1 := i + 1;
  1598.                until
  1599.                   i = 0
  1600.                loop
  1601.                   rc2 := actuals_clients.item(i);
  1602.                   if not rc2.compile_to_c_done then
  1603.                      cc2 := rc2.actuals_clients.count;
  1604.                      if cc2 > cc1 then
  1605.                         rc1 := rc2;
  1606.                         cc1 := cc2;
  1607.                      end;
  1608.                   end;
  1609.                   i := i - 1;
  1610.                end;
  1611.                if rc1 = Current then
  1612.                   really_compile_to_c;
  1613.                else
  1614.                   rc1.compile_to_c(deep - 1);
  1615.                end;
  1616.             end;
  1617.          end;
  1618.       ensure
  1619.          cpp.on_c
  1620.       end;
  1621.  
  1622. feature {RUN_CLASS}
  1623.  
  1624.    actuals_clients: FIXED_ARRAY[RUN_CLASS];
  1625.  
  1626. feature {CREATION_CALL_3_4,RUN_FEATURE}
  1627.  
  1628.    add_client(rc: RUN_CLASS) is
  1629.       require
  1630.          rc /= Void
  1631.       local
  1632.          i: INTEGER;
  1633.       do
  1634.          i := actuals_clients.fast_index_of(rc);
  1635.          if i > actuals_clients.upper then
  1636.             actuals_clients.add_last(rc);
  1637.          end;
  1638.       end;
  1639.  
  1640. feature
  1641.  
  1642.    offset_of(rf2: RUN_FEATURE_2): INTEGER is
  1643.          -- Compute the displacement to access `rf2' in the corresponding
  1644.          -- C struct to remove a possible stupid switch.
  1645.          -- Result is in number of bytes.
  1646.       require
  1647.          at_run_time;
  1648.          writable_attributes.fast_has(rf2);
  1649.          small_eiffel.is_ready
  1650.       local
  1651.          wa: like writable_attributes;
  1652.          t: TYPE;
  1653.          i: INTEGER;
  1654.       do
  1655.          if is_tagged then
  1656.             Result := (1).object_size;
  1657.          end;
  1658.          from
  1659.             wa := writable_attributes;
  1660.             i := wa.upper;
  1661.          invariant
  1662.             i > 0
  1663.          until
  1664.             wa.item(i) = rf2
  1665.          loop
  1666.             t := wa.item(i).result_type;
  1667.             Result := Result + t.c_sizeof;
  1668.             i := i - 1;
  1669.          end;
  1670.       end;
  1671.  
  1672. feature
  1673.  
  1674.    wa_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1675.       once
  1676.          !!Result.with_capacity(24);
  1677.       end;
  1678.  
  1679.    wa_cyclic_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1680.       once
  1681.          !!Result.with_capacity(24);
  1682.       end;
  1683.  
  1684. feature {RUN_CLASS}
  1685.  
  1686.    is_wa_cycle(origin: like Current): BOOLEAN is
  1687.       do
  1688.          if Current = origin then
  1689.             Result := true;
  1690.          end;
  1691.       end;
  1692.  
  1693. feature {RUN_FEATURE_2}
  1694.  
  1695.    force_c_recompilation_comment(rf2: RUN_FEATURE_2) is
  1696.       require
  1697.          at_run_time;
  1698.          writable_attributes.fast_has(rf2);
  1699.          small_eiffel.is_ready
  1700.       do
  1701.          cpp.put_recompilation_comment(offset_of(rf2));
  1702.       end;
  1703.  
  1704. feature -- Some usefull JVM opcode :
  1705.  
  1706.    opcode_checkcast is
  1707.          -- May produce a `checkcast' opcode depending on
  1708.          -- `current_type' Java byte-code mapping.
  1709.       local
  1710.          ct: TYPE;
  1711.          idx: INTEGER;
  1712.       do
  1713.          ct := current_type;
  1714.          if ct.is_basic_eiffel_expanded then
  1715.          elseif ct.is_native_array then
  1716.             tmp_string.clear;
  1717.             ct.jvm_target_descriptor_in(tmp_string);
  1718.             idx := constant_pool.idx_class2(tmp_string);
  1719.             code_attribute.opcode_checkcast(idx);
  1720.          elseif ct.is_bit then
  1721.          else
  1722.             idx := jvm_constant_pool_index;
  1723.             code_attribute.opcode_checkcast(idx);
  1724.          end;
  1725.       end;
  1726.  
  1727.    opcode_instanceof is
  1728.       require
  1729.          not current_type.is_basic_eiffel_expanded
  1730.       local
  1731.          idx: INTEGER;
  1732.       do
  1733.          idx := jvm_constant_pool_index;
  1734.          code_attribute.opcode_instanceof(idx);
  1735.       end;
  1736.  
  1737.    opcode_getfield(rf2: RUN_FEATURE_2): INTEGER is
  1738.          -- Produce a `checkcast'/`getfield' for the given
  1739.          -- attribute of the top object of the stack.
  1740.          -- stack: ... object => ... value
  1741.       local
  1742.          idx: INTEGER;
  1743.       do
  1744.          opcode_checkcast;
  1745.          idx := constant_pool.idx_fieldref(rf2);
  1746.          Result := rf2.result_type.jvm_stack_space - 1;
  1747.          code_attribute.opcode_getfield(idx,Result);
  1748.       end;
  1749.  
  1750. feature {RUN_FEATURE}
  1751.  
  1752.    get_default_rescue(n: FEATURE_NAME): COMPOUND is
  1753.       local
  1754.          a_rescue: RUN_FEATURE_3;
  1755.          target: IMPLICIT_CURRENT;
  1756.          call_to_default_rescue: PROC_CALL_0;
  1757.       do
  1758.          a_rescue := base_class.get_default_rescue(Current,n);
  1759.          if a_rescue /= Void then
  1760.             !!target.make(n.start_position);
  1761.             !!call_to_default_rescue.make(target,a_rescue.name);
  1762.             !!Result.make(Void,call_to_default_rescue,Void);
  1763.          end;
  1764.       end;
  1765.  
  1766.    add_rf(rf: RUN_FEATURE; key: STRING) is
  1767.       do
  1768.          check
  1769.             not feature_dictionary.has(key)
  1770.          end;
  1771.          feature_dictionary.put(rf,key);
  1772.       end;
  1773.  
  1774. feature {CONVERSION_HANDLER}
  1775.    
  1776.    shared_attributes(other: RUN_CLASS) is
  1777.       local
  1778.          rf2: RUN_FEATURE_2;
  1779.          i: INTEGER;
  1780.       do
  1781.          from
  1782.             i := 1;
  1783.          until
  1784.             i > feature_dictionary.count
  1785.          loop
  1786.             rf2 ?= feature_dictionary.item(i);
  1787.             if rf2 /= Void then
  1788.                rf2 ?= other.get_feature(rf2.name);
  1789.             end;
  1790.             i := i + 1;
  1791.          end;
  1792.       end;
  1793.  
  1794. feature {NONE}
  1795.  
  1796.    mark_attribute(body: STRING; rf2: RUN_FEATURE_2) is
  1797.       do
  1798.          tmp_string.copy("o->_");
  1799.          tmp_string.append(rf2.name.to_string);
  1800.          tmp_string.append(fz_open_c_comment);
  1801.          offset_of(rf2).append_in(tmp_string);
  1802.          tmp_string.append(fz_close_c_comment);
  1803.          gc_handler.mark_for(body,tmp_string,rf2.result_type.run_class);
  1804.       end;
  1805.  
  1806.    gc_set_fsoh_marked_in(body: STRING) is
  1807.       do
  1808.          if current_type.is_reference then
  1809.             body.append("((gc");
  1810.             id.append_in(body);
  1811.             body.append("*)o)->header.flag=FSOH_MARKED;%N");
  1812.          end;
  1813.       end;
  1814.  
  1815.    need_gc_mark: BOOLEAN is
  1816.       require
  1817.          at_run_time
  1818.       local
  1819.          i: INTEGER;
  1820.          wa: like writable_attributes;
  1821.          rf2: RUN_FEATURE_2;
  1822.          t: TYPE;
  1823.       do
  1824.          wa := writable_attributes;
  1825.          if wa /= Void then
  1826.             from
  1827.                i := wa.upper;
  1828.             until
  1829.                Result or else i = 0
  1830.             loop
  1831.                rf2 := wa.item(i);
  1832.                t := rf2.result_type;
  1833.                Result := t.need_gc_mark_function;
  1834.                i := i - 1;
  1835.             end;
  1836.          end;
  1837.       end;
  1838.  
  1839.    wa_cycle: FIXED_ARRAY[RUN_FEATURE_2] is
  1840.       once
  1841.          !!Result.with_capacity(24);
  1842.       end;
  1843.  
  1844.    tmp_string: STRING is
  1845.       once
  1846.          !!Result.make(32);
  1847.       end;
  1848.  
  1849.    efnf(bc: BASE_CLASS; fn: FEATURE_NAME) is
  1850.       require
  1851.          bc /= Void;
  1852.          fn /= Void
  1853.       do
  1854.          eh.append("Current type is ");
  1855.          eh.append(current_type.run_time_mark);
  1856.          eh.append(". There is no feature ");
  1857.          eh.append(fn.to_string);
  1858.          eh.append(" in class ");
  1859.          eh.append(bc.name.to_string);
  1860.          error(fn.start_position,fz_dot);
  1861.       end;
  1862.  
  1863.    sort_wam(wam: like writable_attributes) is
  1864.          -- Sort `wam' to common attribute at the end.
  1865.       require
  1866.          wam.lower = 1
  1867.       local
  1868.          min, max, buble: INTEGER;
  1869.          moved: BOOLEAN;
  1870.       do
  1871.          from
  1872.             max := wam.upper;
  1873.             min := 1;
  1874.             moved := true;
  1875.          until
  1876.             not moved
  1877.          loop
  1878.             moved := false;
  1879.             if max - min > 0 then
  1880.                from
  1881.                   buble := min + 1;
  1882.                until
  1883.                   buble > max
  1884.                loop
  1885.                   if gt(wam.item(buble - 1),wam.item(buble)) then
  1886.                      wam.swap(buble - 1,buble);
  1887.                      moved := true;
  1888.                   end;
  1889.                   buble := buble + 1;
  1890.                end;
  1891.                max := max - 1;
  1892.             end;
  1893.             if moved and then max - min > 0 then
  1894.                from
  1895.                   moved := false;
  1896.                   buble := max - 1;
  1897.                until
  1898.                   buble < min
  1899.                loop
  1900.                   if gt(wam.item(buble),wam.item(buble + 1)) then
  1901.                      wam.swap(buble,buble + 1);
  1902.                      moved := true;
  1903.                   end;
  1904.                   buble := buble - 1;
  1905.                end;
  1906.                min := min + 1;
  1907.             end;
  1908.          end;
  1909.       end;
  1910.  
  1911.    gt(rf1, rf2: RUN_FEATURE_2): BOOLEAN is
  1912.          -- True if it is better to set attribute `rf1' before
  1913.          -- attribute `rf2'.
  1914.       local
  1915.          bc1, bc2: BASE_CLASS;
  1916.          bf1, bf2: E_FEATURE;
  1917.          bcn1, bcn2: CLASS_NAME;
  1918.       do
  1919.          bf1 := rf1.base_feature;
  1920.          bf2 := rf2.base_feature;
  1921.          bc1 := bf1.base_class;
  1922.          bc2 := bf2.base_class;
  1923.          bcn1 := bc1.name;
  1924.          bcn2 := bc2.name;
  1925.          if bcn1.to_string = bcn2.to_string then
  1926.             Result := bf1.start_position.before(bf2.start_position);
  1927.          elseif bcn2.is_subclass_of(bcn1) then
  1928.             Result := true;
  1929.          elseif bcn1.is_subclass_of(bcn2) then
  1930.          elseif bc1.parent_list = Void then
  1931.             if bc2.parent_list = Void then
  1932.                Result := bcn1.to_string < bcn2.to_string;
  1933.             else
  1934.                Result := true;
  1935.             end;
  1936.          elseif bc2.parent_list = Void then
  1937.          else
  1938.             Result := bc2.parent_list.count < bc1.parent_list.count
  1939.          end;
  1940.       end;
  1941.  
  1942.    writable_attributes_mem: like writable_attributes;
  1943.  
  1944.    really_compile_to_c is
  1945.       require
  1946.          at_run_time
  1947.       local
  1948.          i: INTEGER;
  1949.          rf: RUN_FEATURE;
  1950.       do
  1951.          compile_to_c_done := true;
  1952.          echo.put_character('%T');
  1953.          echo.put_string(current_type.run_time_mark);
  1954.          echo.put_character('%N');
  1955.          from
  1956.             i := 1;
  1957.          until
  1958.             i > feature_dictionary.count
  1959.          loop
  1960.             rf := feature_dictionary.item(i);
  1961.             rf.c_define;
  1962.             i := i + 1;
  1963.         if (i \\ 30) = 0 then
  1964.            cpp.padding_here;
  1965.         end;
  1966.          end;
  1967.          if run_control.invariant_check then
  1968.             if class_invariant /= Void then
  1969.                class_invariant.c_define;
  1970.             end;
  1971.          end;
  1972.      if feature_dictionary.count > 20 then
  1973.         cpp.padding_here;
  1974.      end;
  1975.       ensure
  1976.          compile_to_c_done
  1977.       end;
  1978.  
  1979.    unqualified_name_memory: STRING is
  1980.       once
  1981.          !!Result.make(32);
  1982.       end;
  1983.  
  1984.    fully_qualified_name_memory: STRING;
  1985.  
  1986.    fully_qualified_name_memory2: STRING is
  1987.       once
  1988.          !!Result.make(256);
  1989.       end;
  1990.  
  1991.    store_feature(rf: like get_feature) is
  1992.          -- To update the dictionary from outside.
  1993.          -- Note : this routine is necessary because of recursive call.
  1994.       require
  1995.          rf.run_class = Current
  1996.       local
  1997.          rf_key: STRING;
  1998.       do
  1999.          rf_key := rf.name.to_key;
  2000.          if feature_dictionary.has(rf_key) then
  2001.             check
  2002.                feature_dictionary.at(rf_key) = rf
  2003.             end;
  2004.          else
  2005.             feature_dictionary.put(rf,rf_key);
  2006.             small_eiffel.incr_magic_count;
  2007.          end;
  2008.       ensure
  2009.          get_feature(rf.name) = rf
  2010.       end;
  2011.  
  2012.    get_or_fatal_error(fn: FEATURE_NAME): RUN_FEATURE is
  2013.       do
  2014.          Result := get_feature(fn);
  2015.          if Result = Void then
  2016.             eh.add_position(fn.start_position);
  2017.             eh.append("Feature ");
  2018.             eh.append(fn.to_string);
  2019.             eh.append(" not found when starting look up from ");
  2020.             eh.add_type(current_type,fz_dot);
  2021.             eh.print_as_fatal_error;
  2022.          end;
  2023.       end;
  2024.  
  2025.    runnable_class_invariant_done: BOOLEAN;
  2026.  
  2027.    c_header_pass_level_done: INTEGER;
  2028.  
  2029.    em1: STRING is 
  2030.       "The `deep_twin'/`is_deep_equal' problem comes from this attribute."
  2031.       
  2032. invariant
  2033.  
  2034.    current_type.run_type = current_type;
  2035.  
  2036. end -- RUN_CLASS
  2037.  
  2038.